#pragma once
#include <vector>
#include <string>
#include <functional>
#include <unordered_map>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <typeinfo>

#include <cstdint>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <sys/types.h>    
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>
#include <signal.h>

#include "Log.hpp"
using namespace myLog;

//通用存储数据的容器
class Any{
private:
    Any& Swap(Any& other){
        std::swap(_content, other._content);
        return *this;
    }

public:
    //注意：构造来说，本身是没有的！

    //默认构造
    Any():_content(nullptr){}

    //拷贝构造
    //每一个Any容器都有一个Clone接口
    //但是，很可能other的指向存储的指针是空的，就没办法调用了，所以需要判断一下！
    Any(const Any& other):_content(other._content ? _content = other._content->Clone() : nullptr){}
   
    //通过输入类型的变量来进行构造
    template<class T>
    Any(const T& val):_content(new PlaceHolder<T>(val)){}

    //析构
    ~Any(){delete _content;}

    //赋值重载 
    //返回引用是为了方便连续赋值
    Any& operator=(const Any& other){
        //原本的那个存储的会给到临时对象，出函数作用域后自动析构
        Any(other).Swap(*this);
        return *this;
    }

    //拷贝赋值
    template<class T>
    Any& operator=(const T& val){
        //原本的那个存储的会给到临时对象，出函数作用域后自动析构
        Any(val).Swap(*this);
        return *this;
    }

    //我们还希望能够通过一个接口，获得当前Any容器所存储的内容
    template<class T>
    T* Get(){
        //必须要保证获取的时候，用户输入的类型必须和获取的是一致的！
        assert(_content->Type() == typeid(T));
        return &(static_cast<PlaceHolder<T>*>(_content)->_val);
    }

private:

//Holder是一个父类，它不负责存储任意的数据！它只声明一些基本的虚函数
    class Holder{
    public:
        Holder(){}
        virtual ~Holder() {}
        //可能会有需要拷贝一个存储任意类型数据的容器指针
        virtual Holder* Clone() = 0;
        //有可能需要进行类型的检查，万一外界获取内容的时候，传入的类型和存储的不一样？
        virtual const std::type_info& Type() = 0;
    private:
    };

//PlaceHolder继承Holder父类，它是用来进行存储任意数据的一个类！
    template<class T>
    class PlaceHolder : public Holder{
    public:
        PlaceHolder(){}
        PlaceHolder(const T& val):_val(val){}

        ~PlaceHolder(){}

        virtual Holder* Clone() override{return new PlaceHolder<T>(_val);}

        //detail：return val
        //这里的返回值必须是 const std::type_info& 要不然报错了
        virtual const std::type_info& Type() override{return typeid(T);}

    public:
        T _val;
    };

//Any类内存储一个父类指针，指向的是子类PlaceHolder
//到时候存储，操作，都是通过这个指针进行操作的！
    Holder* _content;
};


/************************************BUFFER模块**************************************/

#define BUFFER_DEFAULT_SIZE 1024

class Buffer{
private:
//辅助函数 -> 方便获取到当前数组的起始位置
    char* Begin(){return &(*_buffer.begin());}

//辅助函数 -> 找到可读位置区间的‘\n’
    char* FindCRLF(){
        void* res = memchr(ReadPos(), '\n', ReadableSize());
        return static_cast<char*>(res);
    }

public:
    //构造函数 必须要初始化两个偏移量和数组
    Buffer():_rindex(0), _windex(0), _buffer(BUFFER_DEFAULT_SIZE){}

    //获取当前的读写位置
    char* ReadPos(){return Begin() + _rindex;}
    char* WrirePos(){return Begin() + _windex;}

    //获取缓冲区 起始位置 or 末尾位置 剩余空间大小
    uint64_t HeadSize(){return _rindex;}
    uint64_t TailSize(){return _buffer.size() - _windex;}

    //获取当前可读空间大小 可写空间大小
    uint64_t ReadableSize(){return _windex - _rindex;}
    uint64_t WritableSize(){return HeadSize() + TailSize();}

    //将读写位置偏移量向后移动len长度
    void RIndexBackward(uint64_t len){
        assert(len <= ReadableSize());  //必须保证 移动长度len不能超过可读空间大小（本质上是不能让rindex超过windex）
        _rindex += len;
    }
    void WIndexBackward(uint64_t len){  
        assert(len <= TailSize());      //必须保证 向后移动的长度len，不能超出后序的空间大小！
        _windex += len;
    }

    //假设要写入长度len的数据，必须要保证当前的空间足够
    void EnsureWritableSize(uint64_t len){
        //末尾空间足够
        if(len <= TailSize()) return;

        //总体空间足够 -> 采取移动
        else if(len <= WritableSize()){
            int rsz = ReadableSize();
            std::copy(ReadPos(), ReadPos() + rsz, Begin()); //把当前所有可读数据移动到开头的位置
            _rindex = 0;
            _windex = rsz;
        }

        //总体空间不足，直接进行扩容(不用过分扩容)
        else _buffer.resize(_windex + len);
    }

    //清空缓冲区
    void Clear(){_rindex = _windex = 0;}

    //对缓冲区的 读or写 操作
    //我们希望的是外界什么数据，都能以一个个字节写入！ -> 所以用的是void*接收
    //但是，void*在拷贝的时候很麻烦，因为void*不能有步长，所以需要转
    //注意，读写完后需要进行偏移量的移动
    void Read(void* buf, uint64_t len){
        if(len == 0) return;
        //读取是不能超过可读的空间的！ //这里可以直接强制要求上层传入的数据不能超过可读空间assert 也可以设置最大读取长度！
        assert(len <= ReadableSize());
        std::copy(ReadPos(), ReadPos() + len, static_cast<char*>(buf));
        RIndexBackward(len);
    }

    void Write(void* data, uint64_t len){
        if(len == 0) return;
        EnsureWritableSize(len);
        const char* d = static_cast<const char*>(data);
        std::copy(d, d + len, WrirePos());
        WIndexBackward(len);
    }

    //针对于读写接口，可能还有一些别的需求：
    //比如读接口可能会以string方式读取
    std::string ReadAsString(uint64_t len){
        assert(len <= ReadableSize());
        std::string ret(len, '0');
        Read(&ret[0], len);
        return ret;
    }

    
    void WriteByString(const std::string& data){Write((char*)data.c_str(), data.size());} //对于写接口：可能会有希望以string方式写入
    void WriteByBUffer(Buffer& other){Write(other.ReadPos(), other.ReadableSize());}      //可能还会希望以别的buffer对象来进行写入

    //如果是针对于HTTP协议，我们还希望能读到一行的内容
    std::string GetOneLine(){
        char* pos = FindCRLF();
        if(pos == nullptr) return "";
        //len表示的是读起始位置到换行符前一个位置的长度
        int len = pos - ReadPos() + 1;
        return ReadAsString(len + 1); //直接把'\n'符也给读取出来('\r'是一定被读出来的！)
    }

private:
    uint64_t _rindex;           //读偏移量
    uint64_t _windex;           //写偏移量
    std::vector<char> _buffer;  //缓冲区
};

/************************************BUFFER模块**************************************/




/************************************SOCKET模块**************************************/

#define BACKLOG_DEFAULT 128

class Socket{
public:
//构造和析构
    Socket():_sockfd(-1){}
    Socket(int sockfd):_sockfd(sockfd){}
    ~Socket(){Close(_sockfd);}

//获取文件描述符
    int Fd(){return _sockfd;}

//创建套接字
    bool CreateSocket(){
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(_sockfd < 0) {
            LOG(LogLevel::FATAL) << "SOCKET CREATE ERROR!";
            return false;
        }
        LOG(LogLevel::INFO) << "SOCKET CREATE SUCCESS! SOCKFD IS " << _sockfd;
        return true;
    }

//绑定套接字到指定的端口/IP -> 只有服务器需要进行绑定
    bool Bind(uint16_t port, const std::string& ip){
        //设置相关的信息
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(addr);
        //进行绑定
        int bind_ret = bind(_sockfd, (sockaddr*)&addr, len); 
        if(bind_ret < 0){
            LOG(LogLevel::FATAL) << "SOCKET BIND ERROR!";
            return false;
        }
        return true;
    }

//对连接进行监听
    bool Listen(int backlog = BACKLOG_DEFAULT){
        int listen_ret = listen(_sockfd, backlog);
        if(listen_ret < 0){
            LOG(LogLevel::FATAL) << "SOCKET LISTEN ERROR!";
            return false;
        }
        return true;
    }

//获取连接，加入到内核 -> 可以获取到一个新的fd
    int Accept(){
        sockaddr_in client;
        socklen_t len = sizeof(client);
        int fd = accept(_sockfd, (sockaddr*)&client ,&len);
        if(fd < 0) {
            if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return fd;
            else LOG(LogLevel::FATAL) << "SOCKET ACCEPT ERROR!";    
        }         
        return fd;
    }

//如果有写客户端的话，客户端需要进行连接
    bool Connect(uint16_t port, const std::string& ip){
        sockaddr_in peer;
        peer.sin_family = AF_INET;
        peer.sin_port = htons(port);
        peer.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(peer);
        int connect_ret = connect(_sockfd, (sockaddr*)&peer, len);
        if(connect_ret < 0){
            LOG(LogLevel::FATAL) << "SOCKET CONNECT ERROR!";
            return false;                   
        }
        return true;
    }

//创建服务端的套接字 (只有flag为真，才设置非阻塞！)
    bool CreateServer(uint16_t port, const std::string& ip = "0.0.0.0", bool flag = false){
        //服务端的创建一般分为5步：
        if(!CreateSocket()) return false;           //1.创建一个sockfd
        if(flag) SetNonBlock();                     //2.设置文件描述符非阻塞 -> 后序使用epoll关注的
        if(!Bind(port, ip)) return false;           //3.绑定服务器对应的端口号(ip是随意的)
        if(!Listen())       return false;           //4.让服务器进行监听
        ReuseAddr();                                //5.设置地址和端口号复用
        return true;
    }
    
//创建客户端的套接字
    bool CreateClient(uint16_t port, const std::string& ip, bool flag = false){
        if(!CreateSocket()) return false;  //1.创建一个sockfd
        if(!Connect(port, ip)) return false;
        if(flag) SetNonBlock();
        return true;
    }

//关闭连接
    void Close(int sockfd){
        if(_sockfd != -1) close(_sockfd);
        _sockfd = -1;
    }

//设置文件描述符的非阻塞
    void SetNonBlock(){
        int flag = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
    }

//让服务器进行ip地址和端口号的重用(解决TIMEWAIT状态)
    void ReuseAddr(){
        int opt = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        opt = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
    }

//收信息
/**
 * @brief 接收网络数据
 * @return >0 接收到的字节数
 *         =0 非阻塞模式下无数据可用（非错误）
 *         -1 发生错误（检查errno）
 *            - ECONNRESET: 对端关闭连接
 *            - 其他: 真实网络错误
 */
    ssize_t Recv(void* readbuffer, size_t len, int flag = 0){
        if(len == 0) return 0;
        int n = recv(_sockfd, readbuffer, len, flag);
        if(n <= 0){
            //返回0表示：套接字没有出错，但表示此次没有接收数据，下一次可以重新接收(只有非阻塞才有)
            if(n < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) return 0;
            if(n == 0) {
                LOG(LogLevel::INFO) << "CONNECTION CLOSED BY PEER";
                errno = ECONNRESET;
            }
            else LOG(LogLevel::ERROR) << "SOCKET RECV ERROR";
            //其余情况，不管是n == 0还是n < 0，统一当错误！
            return -1;
        }
        return n;
    }

    ssize_t NonBlockRecv(void* readbuffer, size_t len){
        return Recv(readbuffer, len, MSG_DONTWAIT);
    }

//发消息
    ssize_t Send(void* writebuffer, size_t len, int flag = 0){
        if(len == 0) return 0;
        int n = send(_sockfd, writebuffer, len, flag);
        if(n < 0){
            if(n < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) return 0;
            LOG(LogLevel::ERROR) << "SOCKET SEND ERROR";
            return -1;
        }
        return n;
    }

    ssize_t NonBlockSend(void* readbuffer, size_t len){
        return Send(readbuffer, len, MSG_DONTWAIT);
    }

private:
    int _sockfd; 
};

/************************************SOCKET模块**************************************/




/************************************CHANNEL模块**************************************/

class Epoller;
class EventLoop;


//Channel是一个管理事件的一个模块 
//但是，它只是用于辅助管理，真正的管理是Epoll！ -> 这个模块到时候肯定要和上层的Epoll进行关联！甚至是上层的管理事件就绪的模块！
class Channel{
private:
    using Event_CallBack = std::function<void()>;
public:
    Channel(int fd, EventLoop* el):_fd(fd), _events(0), _revents(0), _eventloop(el){}
    ~Channel(){}

    int Fd(){return _fd;} //获取关注的描述符

    //就绪事件是上层带给Channel的，通过该接口设置进来，然后根据情况进行回调！
    void ReventsSet(uint32_t revs){_revents = revs;} 
    //外部进行监控的时候，需要根据Channel获取要监控的事件
    uint32_t EventsGet(){return _events;}


    //设置不同事件就绪时，所需要处理的回调函数！(上层负责监控，然后把事件带给这里，然后根据就绪事件和回调执行！)
    void ReadCallback_Set(const Event_CallBack& read_cb){_read_callback = read_cb;}
    void WriteCallback_Set(const Event_CallBack& write_cb){_write_callback = write_cb;}
    void ErrorCallback_Set(const Event_CallBack& error_cb){_error_callback = error_cb;}
    void CloseCallback_Set(const Event_CallBack& close_cb){_close_callback = close_cb;}
    void AnyCallback_Set(const Event_CallBack& any_cb){_anyevs_callback = any_cb;}

    //当前事件是否有被监控？
    bool IsReadEventMonitored(){return _events & EPOLLIN;}
    bool IsWriteEventMonitored(){return _events & EPOLLOUT;}

    //设置要监控的事件 (一般只需要手动设置关注读写)
    void SetReadEventMonitor(){_events |= EPOLLIN; UpdateEvent();}
    void SetWriteEventMonitor(){_events |= EPOLLOUT; UpdateEvent();}
    void SetEventMoniter(uint32_t events){_events = events;}

    //移除事件的监控
    void DelReadEventMonitor(){_events &= ~EPOLLIN; UpdateEvent();}
    void DelWriteEventMonitor(){_events &= ~EPOLLOUT; UpdateEvent();}
    void DelAllEventsMonitor(){_events = 0; UpdateEvent();}
    
    void Remove();          //这里提供一个接口，就是可以让上层的epoll监控进行内核层面的fd的取消关心 的处理
    void UpdateEvent();     //专门用于调用epoller回调指针，把修改后的关心的事件重新设置到内核epoll！

    //根据就绪事件和回调函数，对事件进行处理
    //需要注意：如果回调没有设置，没办法执行！会变成空指针的解引用！所以需要特判！
    void HandlerRevents(){
        /*EPOLLIN可读事件已经就绪 -> 可以处理数据了*/
        /*EPOLLRDHUP是对方关闭连接的读端了(但是还有可能会向我方发送数据)，此时也需要进行尽快处理数据*/
        /*EPOLLPRI是对方有紧急数据要进行处理(优先带外数据)，此时需要进行尽快处理数据*/
        if(((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI)) && _read_callback) {
            if(_read_callback) _read_callback();
        }

        /*对于下面这些：可能会断开连接的回调，一次执行一个*/
        if((_revents & EPOLLOUT) && _write_callback) {
            if(_write_callback) _write_callback();        /*写事件就绪*/
        }
        //对于读写来说，读写完成后再来调用任意事件的回调！ 比如刷新活跃度
        //因为先刷新，再读写，万一读写量过大就超时了！

        //对于可能导致出错 -> 关闭连接的，一次只处理一个！
        //后序需要先处理任意事件的回调！ 因为错误处理后，就没办法再执行任意事件了
        else if((_revents & EPOLLERR) && _error_callback) {
            /*错误事件就绪*/
            if(_error_callback) 
                _error_callback();
        }
        else if((_revents & EPOLLHUP) && _close_callback){
            /*对方挂断读写端，整个连接关闭*/
            if(_close_callback) _close_callback();
        }

        if(_anyevs_callback) _anyevs_callback();
    }

private:
    int _fd;                            //要关注的文件描述符 -> 关注事件用的
    /*所谓的事件，其实就是一个个的宏，而且只有一个bit位 == 1*/
    uint32_t _events;                   //关注的事件是什么
    uint32_t _revents;                  //具体返回的就绪事件
    EventLoop* _eventloop;             //为了能够和Epoller进行联动，这里需要有一个回指指针！

    Event_CallBack _read_callback;     //读事件触发后的回调
    Event_CallBack _write_callback;    //写事件触发后的回调
    Event_CallBack _error_callback;    //错误事件触发后的回调
    Event_CallBack _close_callback;    //关闭连接事件触发后的回调
    Event_CallBack _anyevs_callback;   //任意事件触发后的回调 -> 比如刷新活跃度！

};



/************************************CHANNEL模块**************************************/




/************************************Epoller模块**************************************/

#define MAX_REVS_SIZE 1024

class Epoller{
private:
//辅助函数

//1.对epoll_ctl的封装
    void Update(Channel* ch, int op){
        int fd = ch->Fd();
        epoll_event ev;
        ev.events = ch->EventsGet();
        ev.data.fd = fd;
        int n = epoll_ctl(_epfd, op, fd, &ev);

        if(n < 0) LOG(LogLevel::WARNING) << "EPOLL CONTROL ERROR!";
    }

//2.判断Channel是否存在
    bool IsChannelExist(Channel* ch){return _channels.find(ch->Fd()) != _channels.end();}

public:
    Epoller()
        :_epfd(-1)
    {
        _epfd = epoll_create(MAX_REVS_SIZE);
        if(_epfd < 0){
            LOG(LogLevel::FATAL) << "EPOLL CREATE ERROR!";
            abort(); //直接退出
        }
    }

    ~Epoller(){}

    //把Channel内的要关注的就绪事件添加到epoll内核！
    void UpdateEvent(Channel* ch){
        //当前要关注是的事件是不存在的 -> 进行添加
        if(!IsChannelExist(ch)) {
            Update(ch, EPOLL_CTL_ADD);
            //不仅仅是添加到内核，还需要添加到哈希
            _channels[ch->Fd()] = ch;
        }
        else {
            Update(ch, EPOLL_CTL_MOD);
            //不仅仅是更新内核，也要更新
        }
    }

    //把指定的channel的对应的关心事件进行移除！
    void RemoveEvent(Channel* ch){
        if(IsChannelExist(ch)) {
            Update(ch, EPOLL_CTL_DEL);
            //不仅仅是要移除内核中的关心，还必须把哈希表中的也给删了！
            _channels.erase(ch->Fd());

            // 3. 清除可能的残留事件（防御性编程）
            for (int i = 0; i < MAX_REVS_SIZE; ++i) {
                if (_revs[i].data.fd == ch->Fd()) _revs[i].events = 0;  // 标记为无效
            }
        }
    }

    //让epoll对事件进行监控，返回就绪的事件！ 这个肯定是给到时候调用Channel进行事件回调处理的模块使用的！
    void EpollWait(std::vector<Channel*>&  active, int timeout = -1){
        //超时时间：-1阻塞  0就是正常轮询  >0就是超时值
        //这里默认给阻塞就好了
        int n = epoll_wait(_epfd, _revs, MAX_REVS_SIZE, timeout);
        if(n < 0){
            //如果是因为信号中断导致的监控错误，那这个无所谓，下次再来监控！
            if(errno == EINTR) return;
            LOG(LogLevel::FATAL) << "EPOLL WAIT ERROR!";
            abort();
        }

        //如果能正常走下来，说明就绪事件已经全部塞入到_revs数组 -> 要带出去！
        for(int i = 0; i < n; ++i){
            //对于外界使用的来讲：需要知道的就是什么事件就绪了！
            ///就绪的Channel一定是在_channels表内的，如何找到？ -> 通过就绪时间 epoll_event tmp 的data.fd字段！(加入关心的时候，设置了该字段！)
            epoll_event rev = _revs[i];
            int fd = rev.data.fd;

            //ch就是当前就绪的事件所处在的Channel
            auto ch = _channels.find(fd);   
            assert(ch != _channels.end());

            //设置事件 + 返回就绪事件到上层
            ch->second->ReventsSet(rev.events);
            active.push_back(ch->second);
        }
    }

    void Debug(){
        for(auto& ch : _channels){
            std::cout << "fd" << ch.first << " ";
        }
        std::cout << std::endl;
    }

private:
    int _epfd;
    epoll_event _revs[MAX_REVS_SIZE];
    std::unordered_map<int, Channel*> _channels;
};

/************************************Epoller模块**************************************/








/************************************EventLoop模块**************************************/



/****************子模块：TimerWheel定时器****************/

//这个是定时任务的类：使用智能指针 + 析构的方式来执行超时任务(即析构的时候)
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;

//定时器任务类
class TimerTask{
public:
    TimerTask(uint64_t id, int timeout, TaskFunc task_cb):_id(id), _timeout(timeout),_iscanceled(false), _task_cb(task_cb){}

    ~TimerTask(){
        if(!_iscanceled) _task_cb();
        _release();
    }

    void SetCancel(){_iscanceled = true;}
    void SetRelease(const ReleaseFunc& release){_release = release;}
    int GetTimeout(){return _timeout;}
private:
    uint64_t _id;           //每个定时任务的id
    int _timeout;           //设置超时时间，表示定时多久后进行检测
    bool _iscanceled;       //是否取消定时任务 true表示取消， false表示不取消
    TaskFunc _task_cb;      //表示这是当定时器到时后，需要执行的任务
    ReleaseFunc _release;   //表示触发析构的受要做的事情！
};


//定时轮类：通过秒指针，每一秒向后走一步，队内部的shared_ptr进行释放(可能是引用计数、也可能是真的析构)
//所谓刷新，其实就是找到轮询数组上延时的位置重新插入一个shared_ptr
//当真的超时了，必然被析构释放，执行绑定的回调即可！

//但是需要明白这里是如何实现每秒触发一次的？即每秒进行超时任务检测和执行？
//使用timerfd来操作！   -> 每秒触发一次，让epoll关心即可！
//然后一旦触发，就执行回调即可！
class TimerWheel{
private:
    using Task_ShaPtr = std::shared_ptr<TimerTask>;
    using Task_WeaPtr = std::weak_ptr<TimerTask>;
private:
    bool IsTimerExist(uint64_t id){ return _timers.find(id) != _timers.end();}

    void RemoveTimer(uint64_t id){
        //找不到该id对应的任务 无法进行删除
        if(!IsTimerExist(id)) return;
        //反之找得到，直接进行删除
        _timers.erase(id);
    }

    //创建timerfd
    int CreateTimerFd(){
        int tfd = timerfd_create(CLOCK_MONOTONIC, 0);
        if(tfd < 0){
            LOG(LogLevel::FATAL) << "TIMERFD CREATE ERROR!";
            abort();
        }

        //然后需要设置超时时间
        itimerspec itime;
        /*it_value设置的是第一次要几秒后触发超时*/
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0;
        /*it_interval设置的是，后面每一次超时的间隔时间*/
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv_nsec = 0;
        /*把超时时间的相关设置设置到该fd*/
        timerfd_settime(tfd, 0, &itime, nullptr);
        return tfd;
    }

    int_least64_t ReadTimerFd(){
        uint64_t t;
        int n = read(_timerfd, &t, 8);
        if(n < 0){
            LOG(LogLevel::FATAL) << "TIMERFD READ ERROR!";
            abort();
        }
        return n;
    }
    void TimerRun(){
        _tick = (_tick + 1) % _capacity;
        _wheels[_tick].clear();
    }
    //这个是超时任务执行的回调
    void OnTime(){
        //1.先把文件描述符的内容进行读取
        int m = ReadTimerFd();
        //2.每超时一次，秒针移动一次 但是超时次数就是timerfd读取出来的次数，所以，读出来多少次，就要执行多少次！
        for(int i = 0; i < m; ++i){
            TimerRun();
        }
    }

    //在指定位置添加超时任务
    void TimerAddInLoop(uint64_t id, int timeout, const TaskFunc& cb){
        //如果这个id已经存在了，就没必要再进行插入了
        if(IsTimerExist(id)) return;

        //反之需要：
        //1.先构造一个Task_ShaPtr用于插入_wheels
        Task_ShaPtr sha(new TimerTask(id, timeout, cb));

        //2.为这个新加入的任务设置回调(超时的回调已经设置了（cb）)
        //但是因为超时后，如果真的被析构了，那么_timers内也不能存在对应id的指针！
        sha->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));

        //3.搞一个weakptr的，保存在_timers，因为后序刷新的时候用得到！(一定不能用shared版本的！)
        //4.插入weakptr
        _timers[id] = Task_WeaPtr(sha);

        //5.把shared_ptr添加到时间轮
        int pos = (_tick + timeout) & _capacity;
        _wheels[pos].push_back(sha);
    }

    //刷新任务对应的超时时间
    void TimerRefreshInLoop(uint64_t id) {
        auto it = _timers.find(id);
        if (it == _timers.end()) return;  // 任务不存在或已超时

        Task_ShaPtr pt = it->second.lock();
        if (!pt) {
            _timers.erase(id);  // 清理无效的弱指针
            return;
        }

        // 重新插入到新的槽位
        int pos = (_tick + pt->GetTimeout()) % _capacity;
        _wheels[pos].push_back(pt);
    }

    void TimerCancelInLoop(uint64_t id){
        if(!IsTimerExist(id)) return;
        _timers[id].lock()->SetCancel();
        _timers.erase(id);
    }

public:
    TimerWheel(EventLoop* loop, int capacity = 60)
        :_tick(0), _capacity(capacity), _wheels(_capacity), 
        _loop(loop), _timerfd(CreateTimerFd()), _timer_ch(std::make_unique<Channel>(_timerfd, _loop))
    {
        //然后，需要到eventloop内的epoll模型那里，设置该timerfd的读事件关心！还有读回调
        //每个一秒触发一次超时，timerfd的读事件就绪 -> 可以进行读取操作！
        _timer_ch->ReadCallback_Set(std::bind(&TimerWheel::OnTime, this));
        _timer_ch->SetReadEventMonitor();
    }

    ~TimerWheel(){}

    /*今天这里，对于超时任务添加、刷新，是否执行等逻辑，我们不能直接在这里执行！*/
    /*因为，未来有可能是用线程池队业务进行处理，这一下就引发线程安全了*/
    /*我们需要实现的目标：让任务一定要在同一个线程内执行！ 要不然加锁非常拉底效率*/

    //这三个用到了前置声明的EventLoop，只能放到外面去定义了！
    void TimerAdd(uint64_t id, int timeout, const TaskFunc& cb);
    void TimerRefresh(uint64_t id);
    void TimerCancel(uint64_t id);

    bool HasTimer(uint64_t id){
        return IsTimerExist(id);
    }
    

private:
    int _tick;                                          //tick指针，指向的是 _wheels数组，指哪执行哪里的任务
    int _capacity;                                      //表示的是轮定数组最大容量
    std::vector<std::vector<Task_ShaPtr>> _wheels;      //用来管理所有的定时任务的
    std::unordered_map<int, Task_WeaPtr>  _timers;      //用weak_ptr来保存shared_ptr的值，方便刷新的时候用
    
    EventLoop* _loop;                                   //绑定的eventloop
    int _timerfd;                                       //用于设置定时触发的fd -> 以便每秒轮询检测
    std::unique_ptr<Channel> _timer_ch;                 //这个是管控着_timerfd的Channel类

};



/****************子模块：TimerWheel定时器****************/





//这个模块是一个线程对应一个(从Reactor)
class EventLoop{
private:
    using Functor = std::function<void()>;

    //判断当前线程是否是eventloop绑定的thread
    bool IsInLoop(){return _thread_id == std::this_thread::get_id();}

    int CreateEventFd(){
        int evfd = eventfd(1, EFD_CLOEXEC | EFD_NONBLOCK);
        if(evfd < 0){
            LOG(LogLevel::FATAL) << "EVENTFD CREATE ERROR!!!";
            abort();    //创建失败直接返回
        }
        return evfd;
    }

    void SignalEventFd(){
        uint64_t data = 1;
        int n = write(_eventfd, &data, sizeof(data));
        if(n < 0){
            //如果是因为信号终止 或 非阻塞错误 -> 不需要处理
            if(errno == EINTR || errno == EAGAIN) return;
            LOG(LogLevel::ERROR) << "EVENTFD WRITE ERROR!";
            abort();    //要不然是真的错了 直接异常返回
        }
    }

    void EventFdRead(){
        //进行读取eventfd
        uint64_t res = 0;
        int n = read(_eventfd, &res, sizeof(res));
        if(n < 0){
            if(errno == EINTR || errno == EAGAIN) return;
            LOG(LogLevel::ERROR) << "EVENTFD READ ERROR!";
            abort();
        }
    }

public:
    EventLoop()
        :_thread_id(std::this_thread::get_id()),
        _eventfd(CreateEventFd()),
        _eventfd_ch(std::make_unique<Channel>(_eventfd, this)),
        _tm(this)

    {
        //然后，我们需要对eventfd的读事件设置回调，并进行读事件的关心(对于eventloop来说，只需要进行EPOLLIN的关心)
        //因为这个evfd，可能是主reactor通知的新连接事件，有可能任务入队列触发的事件！  
        _eventfd_ch->ReadCallback_Set(std::bind(&EventLoop::EventFdRead, this));
        _eventfd_ch->SetReadEventMonitor();
    }
    ~EventLoop(){}

    //在eventloop模块进行事件的更新/删除
    void UpdateEvent(Channel* ch){_epoller.UpdateEvent(ch);}
    void RemoveEvent(Channel* ch){_epoller.RemoveEvent(ch);}

    //判断要运行的任务是否是在当前线程内的(其实就是判断是否是别的线程带进来的)
    //如果是当前线程的任务，那就直接直接执行，反之进入任务队列
    void RunInLoop(const Functor& cb){
        if(IsInLoop()) cb();
        else TaskInQueue(cb);
    }

    //把任务加到任务队列
    void TaskInQueue(const Functor& cb){
        //出了这个作用域自动解锁
        {
            //相当于是Lock_guard
            std::unique_lock<std::mutex> guard(_lock);
            _tasks.push_back(cb);
        }
        //但是，现在可能会有一个问题：
        //就是当前eventloop正在阻塞监听网络IO的事件，一直没有连接！
        //但是其他线程把任务压入到任务队列，但是因为eventloop的阻塞 -> 导致当前没办法执行
        //所以，我们这里可以主动向当前线程的eventfd写入数据，这样子下一次epoll就监听到了evfd的就绪，就可以执行了！
        SignalEventFd();
    }

    //把所有的处在任务队列的任务进行执行
    void RunAllTaskInQueue(){
        std::vector<Functor> tmp;
        {
            std::unique_lock<std::mutex> guard(_lock);
            _tasks.swap(tmp);
        }
        //出来后就可以执行了
        for(auto& func : tmp) {
            func();
        }
    }

    //对于每个eventloop，需要有一个开启工作的接口！
    /*一般是分为三步：1.进行epollwait 2.就绪事件返回后，执行回调 3.把任务队列内的任务全部执行！*/
    void Start(){
        //1.等待时间就绪
        std::vector<Channel*> active;
        _epoller.EpollWait(active);
        //2.针对于就绪的事件，直接执行！因为是在该线程内触发的
        for(auto& ch : active) ch->HandlerRevents();
        //3.执行任务队列内的任务
        RunAllTaskInQueue();
    }

    //断言必须在当前线程
    void AssertInLoop(){assert(_thread_id == std::this_thread::get_id());}

    //针对于定时器的一些操作
    void TimerAdd(uint64_t id, int timeout, const TaskFunc& cb){_tm.TimerAdd(id, timeout, cb);}
    void TimerRefresh(uint64_t id){_tm.TimerRefresh(id);}
    void TimerCancel(uint64_t id){_tm.TimerCancel(id);}
    /*这个接口只能在eventloop内调用，必须是一个线程内！不能给多线程调用，否则会有线程安全问题！*/
    bool HasTimer(uint64_t id){return _tm.HasTimer(id);}


private:
    std::thread::id _thread_id;                     //当前线程的线程id -> 用于判断调用该eventloop时，是否是绑定的线程？
    Epoller _epoller;                               //每个线程一个！
    int _eventfd;                                   //每个eventloop有一个基于事件通知的机制
    std::unique_ptr<Channel> _eventfd_ch;           //为了方便进行操作，我们需要让每个eventloop使用Channel来对eventfd的事件进行管理
    std::vector<Functor> _tasks;                    //用vector充当任务队列
    std::mutex _lock;                               //任务队列的锁

    TimerWheel _tm;                                 //时间定时器
};

/************************************EventLoop模块**************************************/



//-------------------------------------针对于在EventLoop模块前使用了EventLoop前置声明的调用，需要放到这里来进行实现！-------------------------------------//

//因为Timerwheel中用到了前置声明EventLoop
//同时，这里不能直接插入！需要使用eventloop的RunInLoop接口，是本线程内调用的，直接执行，反之入任务队列
void TimerWheel::TimerAdd(uint64_t id, int timeout, const TaskFunc& cb){_loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop, this, id, timeout, cb));}
void TimerWheel::TimerRefresh(uint64_t id){_loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop, this, id));}
void TimerWheel::TimerCancel(uint64_t id){_loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop, this, id));}


//放到这里来，确保能看到完整的定义！
//需要放在外面来定义
//因为Channel比EventLoop先实现，但是又需要用到，所以只能前向声明
//但是前向声明时不能直接使用的，所以这里必须放最后去实现，以便向上搜索的时候能够搜索到Eventloop
inline void Channel::Remove(){_eventloop->RemoveEvent(this);} 
inline void Channel::UpdateEvent(){_eventloop->UpdateEvent(this);}

//-------------------------------------针对于在EventLoop模块前使用了EventLoop前置声明的调用，需要放到这里来进行实现！-------------------------------------//





/************************************CONNECTION模块**************************************/

//需要设置好connection的连接状态
typedef enum{
    DISCONNECTED,
    CONNECTED,
    CONNECTING,
    DISCONNECTING
}ConnStatu;


//Connection：是对连接的管理模块！所有的操作，都是基于该模块完成！
class Connection;
using ConnPtr = std::shared_ptr<Connection>;       //使用Connection的时候，需要使用shared_ptr 防止被关闭后可能出现野指针
//这里采取的策略是：其余地方使用连接都是通过shared_ptr，这样子的话释放也只是释放引用计数，除非真正到管理连接的模块那里进行最后的删除

//要想使用shared_from_this来拷贝当前的对象到shared_ptr，必须要继承这个类__enable_shared_from_this
class Connection : public std::enable_shared_from_this<Connection>{
public:
/*这四个回调函数都是让外部使用组建的用户进行设置的：用户调用的就是后续的服务器模块！*/
    using ConnectedCallback = std::function<void(const ConnPtr&)>;           //连接建立好后应该执行的回调
    using ClosedCallback = std::function<void(const ConnPtr&)>;              //关闭连接的时候需要执行的
    using MessageCallback = std::function<void(const ConnPtr&, Buffer*)>;    //信息处理的回调函数
    using AnyEventCallback = std::function<void(const ConnPtr&)>;            //任意事件触发后执行的回调
private:

    /*关于Connection内的Channel对应的事件绑定的回调，也就是连接的事件触发后要执行的任务*/
    /*这里执行的回调怎么处理？比如读了写了后应该作什么？其实就是传入进来给连接的回调！*/
    /*事件触发后，回调到这里，再去根据情况回调传进来的回调函数*/

    //描述符可读触发的回调，会把从sock读到的数据放到缓冲区中，然后进行业务处理(业务处理就是_msg_callback)
    void HandlerRead(){
        char buf[65536] = {0};
        ssize_t n = _sock.NonBlockRecv(buf, 65536); //需要特别关注一下返回值！
        if(n < 0) return ShutDownInLoop();       //不能立马关闭连接，需要看看输入输出缓冲区内是否还有数据，有就要处理，然后再考虑关闭

        _inbuffer.Write(buf, n);          //buffer内的write接口操作完后会自动地向后移动指针
        if(_inbuffer.ReadableSize() > 0) _msg_cb(shared_from_this(), &_inbuffer);
    }            

    //描述符可写触发的回调，把输出缓冲区内的数据进行发送(调用sock模块的Send())
    void HandlerWrite(){
        //这个操作只是单纯的读取Readpos开始的数据，没有清空
        ssize_t n = _sock.NonBlockSend(_outbuffer.ReadPos(), _outbuffer.ReadableSize());
        if(n < 0){
            //如果小于0就出错了，这里我们进行检查读缓冲区是否还有数据，如果有就处理一下
            if(_inbuffer.ReadableSize() > 0) _msg_cb(shared_from_this(), &_inbuffer);
            //然后就可以真的进行关闭连接
            Release();
        }
        _outbuffer.RIndexBackward(n);  //清空读取的数据

        //现在还有问题：就是如果当前是带关闭状态 || 写缓冲区没有数据了
        if(_outbuffer.ReadableSize() == 0){
            _conn_ch.DelWriteEventMonitor();   //写缓冲区都没数据了，直接关闭写关心
            if(_statu == DISCONNECTING) Release();;   //缓冲区没数据，还是待关闭状态，直接挂断
        }
    }   

    //描述符要关闭(挂断)的时候触发的回调
    void HandlerClosed(){
        /*一旦连接挂断，sockfd什么也干不了，所以处理一下数据后直接挂断*/
        if(_inbuffer.ReadableSize() > 0) _msg_cb(shared_from_this(), &_inbuffer);
        Release();
    }          

    //描述符出错的时候执行的回调
    void HandlerError(){HandlerClosed();}       

    //描述符触发任意事件的回调  
    //(同时进行超时任务执行的的刷新延时)
    void HandlerAny(){
        //如果设置了超时任务刷新启动
        if(_enable_inactive_release) _loop->TimerRefresh(_conn_id);
        if(_anyev_cb) _anyev_cb(shared_from_this()); 
    }             

    /*这里就是一些私有函数，其实就是对外放开的接口会往这里调用   这是为了保证在同一个线程内的！*/

    //启动超时任务
    void EnableInactiveReleaseInLoop(int timeout){
        _enable_inactive_release = true;                                //设置状态(Connection层)
        if(_loop->HasTimer(_conn_id)) _loop->TimerRefresh(_conn_id);    //如果存在就刷新一下就好了
        else _loop->TimerAdd(_conn_id, timeout, std::bind(&Connection::Release, this));  //反之添加
    }

    //取消超时任务
    void DisableInactiveReleaseInLoop(){
        _enable_inactive_release = false;                               //设置状态
        if(_loop->HasTimer(_conn_id)) _loop->TimerCancel(_conn_id);     //存在才取消超时任务的执行
    }

    //注意：这个不是真的说把数据发送给对端
    //逻辑是这样的：读事件就绪 -> 可读 -> 读回调 -> 接收数据写入inbuffer -> 处理inbuffer数据 -> 数据通过SendInLoop进入到outbuffer -> 启动写监控 -> 等待写就绪发送
    void SendInLoop(char* data, size_t len){
        //如果当前状态是关闭，没办法写
        if(_statu == DISCONNECTED) return;
        //1.写到outbuffer
        _outbuffer.Write(data, len);
        //2.启动写事件关心
        if(_conn_ch.IsWriteEventMonitored() == false) _conn_ch.SetWriteEventMonitor();
    }

    //这里也不是真的把连接给挂断了，而是需要做：1.设置状态为DISCONNECTING 2.判断输入输出缓冲区是否还有数据
    void ShutDownInLoop(){
        _statu = DISCONNECTING;
        if(_inbuffer.ReadableSize() > 0){
            if(_msg_cb) _msg_cb(shared_from_this(), &_inbuffer); //输入缓冲区还有数据 并且能进行处理
        }
        //不直接进行发送 -> 进行写事件的关心 -> 触发写的回调进行发送(前提是当前)
        //万一发送错误，也是会直接进行挂断的！
        if(_outbuffer.ReadableSize() > 0) {
            if(_conn_ch.IsWriteEventMonitored() == false) _conn_ch.SetWriteEventMonitor();
        }
        //反之输出缓冲区没有数据，此时直接挂断
        //注意，要在最后的任务队列里再来做这件事情
        else Release();
    }

    void ExchangeProtocolInLoop(const Any& context, ConnectedCallback& connected, const ClosedCallback& closed, const MessageCallback& msg, const AnyEventCallback& anyev){
        _context = context;
        _connected_cb = connected;
        _closed_cb = closed;
        _msg_cb = msg;
        _anyev_cb = anyev;
    }


    void EstablishInLoop(){
        //1.把当前连接状态设置为CONNECTED
        assert(_statu == CONNECTING);
        _statu = CONNECTED;
        //2.启动读事件的监控(必须在这里执行，因为如果在构造内执行了，就会导致万一有事件就绪(如果超时任务启动的同时)，此时都没添加超时任务，那逻辑就错了)
        _conn_ch.SetReadEventMonitor();
        //3.执行用户给的连接回调
        if(_connected_cb) _connected_cb(shared_from_this());
    }

    //因为ShutDownInLoop(向外提供的)并不是真的关闭，而是把状态设为待关闭状态
    //没数据处理后，才去真的释放，这里用Release做实际释放接口
    void ReleaseInLoop(){
        //1.设置状态为DISCONNECTED
        _statu = DISCONNECTED;
        //2.关闭所有事件监控
        _conn_ch.Remove();
        //3.关闭套接字
        close(_sockfd);
        //4.定时任务的取消
        if(_loop->HasTimer(_conn_id)) {
            _loop->TimerCancel(_conn_id);
        }
        //5.执行回调(先执行用户给的, 否则可能出现错误)
        if(_closed_cb != nullptr) _closed_cb(shared_from_this());
        //6.上述的所有操作都是只是操作connection的副本！真正要进行释放连接，需要在后续的服务器模块内也进行释放
        if(_server_closed_cb) _server_closed_cb(shared_from_this());        
    }


public:
    /*构造和析构*/
    Connection(EventLoop* loop, int conn_id, int sockfd)
        :_loop(loop), _conn_id(conn_id), _sockfd(sockfd), _sock(_sockfd), _conn_ch(_sockfd, _loop), _enable_inactive_release(false), _statu(CONNECTING)
    {
        //设置一些回调函数，其实就是事件触发的时候执行的
        _conn_ch.CloseCallback_Set(std::bind(&Connection::HandlerClosed, this));
        _conn_ch.ReadCallback_Set(std::bind(&Connection::HandlerRead, this));
        _conn_ch.WriteCallback_Set(std::bind(&Connection::HandlerWrite, this));
        _conn_ch.ErrorCallback_Set(std::bind(&Connection::HandlerError, this));
        _conn_ch.AnyCallback_Set(std::bind(&Connection::HandlerAny, this)); 
    }
    ~Connection(){LOG(LogLevel::DEBUG) << "RELEASE CONNECTION : " << this;}

    /*设置回调*/
    /*注意：这些回调为了保证是在同一个线程内执行的，需要调用loop的RunInLoop*/
    /*所以会在私有域内定义一些私有的函数*/
    void SetConnectedCallback(const ConnectedCallback& cb){_connected_cb = cb;}
    void SetClosedCallback(const ClosedCallback& cb){_closed_cb = cb;}
    void SetMessageCallback(const MessageCallback& cb){_msg_cb = cb;}
    void SetAnyEventCallback(const AnyEventCallback& cb){_anyev_cb = cb;}
    void SetServerClosedCallback(const ClosedCallback&cb){_server_closed_cb = cb;}

    /*一些获取状态的*/
    uint64_t Id(){return _conn_id;}
    int Fd(){return _sockfd;}
    bool IsConnected(){return _statu == CONNECTED;} //是否处于已连接状态 -> 有用！
    ConnStatu Statu(){return _statu;}  //获取当前的状态
    Buffer* Inbuffer(){return &_inbuffer;}
    Buffer* Outbuffer(){return &_outbuffer;}
    Channel* ConnChannel(){return &_conn_ch;}

    /*上下文相关处理*/ 
    Any* GetContext(){return &_context;}  //获取上下文 -> 注意要给指针，因为上下文需要切换
    void SetContext(const Any& context){_context = context;}  //设置上下文 


//下面是一些针对于连接管理的操作，为了保证线程安全，也就是在同一个线程内执行，需要调用RunInLoop

    /*启停非活跃连接相关操作*/
    void EnableInactiveRelease(int timeout){_loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, timeout));}
    void DisableInactiveRelease(){_loop->RunInLoop(std::bind(&Connection::DisableInactiveReleaseInLoop, this));}

    /*针对于缓冲区Buffer的操作*/
    //发送数据：并不是真的发送，而是把数据存储在输出缓冲区内，然后到时候写事件就绪了，进入写回调后，再来把数据给发送给对端！
    void Send(char* data, size_t len){_loop->RunInLoop(std::bind(&Connection::SendInLoop, this, data, len));}

    /*提供给组件使用者：关闭当前连接的功能*/
    /*但是实际上，并不是直接关闭：而是需要先对当前缓冲区内数据是否还有进行判断，然后再关闭*/
    void Shutdown(){_loop->RunInLoop(std::bind(&Connection::ShutDownInLoop, this));}

    //注意：所有的要进行释放连接的，都要调用这个接口！因为需要最后来进行释放连接！如果直接释放，后序Connection类都没了，后续的所有操作都是非法的！
    void Release() {_loop->TaskInQueue(std::bind(&Connection::ReleaseInLoop, this));}

    /*提供切换协议的接口*/
    /*所谓切换协议：其实就是切换数据的处理方式(回调)，还有上下文*/
    //这个操作必须要在EventLoop内执行，不要压入队列！因为需要进行快速的协议转化！
    //如果在别的线程执行，会压入loop的任务队列，那么在事件回调处理完前，都没办法切换协议了！
    void ExchangeProtocol(const Any& context, const ConnectedCallback& connected, const ClosedCallback& closed, const MessageCallback& msg, const AnyEventCallback& anyev){
        _loop->AssertInLoop();
        _loop->RunInLoop(std::bind(&Connection::ExchangeProtocolInLoop, this, context, connected, closed, msg, anyev));
    }

    //向外提供的接口
    //操作为：连接获取后，此时需要对一些状态，事件的回调进行设置，都在这里进行！然后启动读的监控
    void Establish(){_loop->RunInLoop(std::bind(&Connection::EstablishInLoop, this));}

    
private:
    EventLoop* _loop;               //连接也是在一个EventLoop下进行操作的！ 需要进行绑定loop

    /*基本成员变量*/
    uint64_t _conn_id;              //当然，每个连接内应该要有定时器的id的！但是为了简单点，直接让Connection和TimerTask同一个id
    int _sockfd;                    //新连接对应的文件描述符
    Socket _sock;                   //套接字管理模块
    Channel _conn_ch;               //事件管理模块
    bool _enable_inactive_release;  //这个是是否设置该连接的超时任务 默认为false，即不设置超时任务

    /*缓冲区*/
    Buffer _inbuffer;               //读取数据后，存储到这里->进行处理
    Buffer _outbuffer;              //写入数据，先放到这里，等待写事件就绪了，再发送！

    /*状态*/
    ConnStatu _statu;               //这个是存放connection的当前连接状态的 不同的状态有不同的操作

    /*上一次处理的上下文*/
    Any _context;                   //数据上次可能没处理完！但是我们不想再重新处理一次处理过的， 所以需要上下文来保存！
    //但是当前不知道是以什么协议格式处理的， 所以就拿通用存储容器Any来接收！
    
    /*一些回调函数*/
    ConnectedCallback _connected_cb;
    ClosedCallback _closed_cb;
    MessageCallback _msg_cb;
    AnyEventCallback _anyev_cb;    

    /*组件内的连接关闭回调  因为服务器组组件(模块)，会用容器管理shared_ptr保存的Connection*/
    //如果真的要断开连接，那么必须要在管理的模块也关了！(也就是析构掉)
    //但是，我们是通过智能指针使用的，只要服务器模块内还有保存Connection，引用计数 >= 1
    //所以，真的需要进行关闭，我们这里还得来一个和外界服务器模块绑定的回调 -> 调用该回调就是执行服务器模块内Connection的释放及连接关闭！
    ClosedCallback _server_closed_cb;
    //但是，这个接口我们是不会放给外界进行调用的！
};

/************************************CONNECTION模块**************************************/





/************************************ACCEPT模块**************************************/

class Acceptor{
private:
    using AcceptCallBack = std::function<void(int)>;

    int CreateServerSocket(uint16_t port, const std::string& ip, bool flag){
        bool ret = _listen_sock.CreateServer(port, ip, flag);
        assert(ret == true);
        return _listen_sock.Fd();
    }

    //Acceptor的读事件就绪的回调函数  ->  去获取连接
    void HandlerRead(){
        int newfd = _listen_sock.Accept();
        if(newfd < 0) return;
        if(_accept_cb) _accept_cb(newfd);
    }

public:

    /*注意：这里不能再构造的时候就启动读事件的监控*/
    /*因为，有可能存在：刚设置好读监控，立马有连接来了，但是如果此时还没有设置好回调就麻烦了*/
    /*那么新到来的连接就没办法被处理*/
    Acceptor(EventLoop* loop, uint16_t port, const std::string& ip = "0.0.0.0", bool flag = false)
        :_loop(loop), _listen_sock(CreateServerSocket(port, ip, flag)), _lis_ch(_listen_sock.Fd(), _loop)
    {
        _lis_ch.ReadCallback_Set(std::bind(&Acceptor::HandlerRead, this));
    }

    ~Acceptor(){}

    void SetAcceptCallback(const AcceptCallBack& acb){_accept_cb = acb;}
    
    void StartListen(){_lis_ch.SetReadEventMonitor();}
    
private:  
    EventLoop* _loop;               //需要有一个loop，因为channel 需要被管理！
    Socket _listen_sock;            //监听套接字
    Channel _lis_ch;                //用于事件管理的套接字
    AcceptCallBack _accept_cb;      //外界传给Acceptor的回调函数
};

/************************************ACCEPT模块**************************************/





/************************************THREADLOOP模块**************************************/

class ThreadLoop{
public:
    ThreadLoop():_loop(nullptr), _thread(std::bind(&ThreadLoop::ThreadEntry, this)){}
    ~ThreadLoop(){}

//到时候所有的loop之间是要进行通信的，所以需要能够获取到！
    //但是存在一个问题：就是到时候上层是能够管理所有的ThreadLoop的，因为要获取到来进行连接派发！
    //但是，如果此时获取到的是空就麻烦了！所以我们这里采用锁 + 条件变量的方式进行阻塞！
    EventLoop* GetLoop(){
        EventLoop* loop = nullptr;
        {
            std::unique_lock<std::mutex> guard(_lock);
            _cond.wait(guard, [&](){return _loop != nullptr;});   //这个wait接口第二个是要传入一个返回值为bool的可调用对象，为假就一直等！
            loop = _loop;
        }
        return loop;
    }

private:
    //这个是到时候线程要执行的函数
    void ThreadEntry(){
        //线程的内部进行创建loop！
        //这里不采用new，因为我们想要让线程和loop同生死！
        EventLoop loop;
        {
            std::unique_lock<std::mutex> guard(_lock);  
            _loop = &loop;
            _cond.notify_all();   //所以这里就是为什么要唤醒所有的线程！
        }
        while(1){
            loop.Start();
        }
    }

private:
    /*如果在这里进行了实例化，就会导致到时候要绑定给loop的id是主线程的！*/
    EventLoop* _loop;       //这个是该线程对应的一个loop 但是需要注意，不能在这里实例化！
    std::thread _thread;    //这个是EventLoop对应的线程
    //注意：必须要先创建线程，再来实例化loop对象！
    //如果先建立多个EventLoop，再来创建线程，把id给loop进行设置 -> 这段时间内loop是无主状态的，其他线程随便用！ -> 引发线程安全问题

    std::mutex _lock;
    std::condition_variable _cond;
};

/************************************THREADLOOP模块**************************************/






/************************************THREADPOOL模块**************************************/
//这个是让上层管理所有的ThreadLoop，方便进行轮询分配、设置线程数
class ThreadPool{
public:
    ThreadPool(EventLoop* base_loop):_thread_num(0), _next_index(0), _base_loop(base_loop){}
    ~ThreadPool(){}

    //设置线程数
    void SetThreadNum(int num){
        assert(_thread_num >= 0);
        _thread_num = num;
    }

    //获取下一个
    EventLoop* NextLoop(){
        assert(_thread_num >= 0);
        if(_thread_num == 0) return _base_loop;
        _next_index = (_next_index + 1) % _thread_num;
        return _loops[_next_index];
    }

    //启动所有的ThreadLoop
    void StartAllThread(){
        if(_thread_num == 0) return;
        _threads.resize(_thread_num);
        _loops.resize(_thread_num);
        for(int i = 0; i < _thread_num; ++i){
            _threads[i] = new ThreadLoop();
            _loops[i] = _threads[i]->GetLoop();
        }
    }

private:
    int _thread_num;                        //从属线程的个数
    int _next_index;                        //下一个被分配的线程的位置

    EventLoop* _base_loop;                  //因为可能存在设置_thread_num == 0的情况，此时就退化为单线程：即进行监控，又负责处理！ -> 所以需要外部创建一个EventLoop传地址进来
    //如果_thread_num != 0的情况 -> 那么_base_loop只进行新连接的获取！

    std::vector<ThreadLoop*> _threads;       //从属线程存储
    std::vector<EventLoop*> _loops;         //从属线程对应eventloop，我们这里一定是一一对应的！ 
};

/************************************THREADPOOL模块**************************************/





/************************************TCPSERVER模块**************************************/

class TcpServer{
private:
    /*今天我们这里采取的策略是：新连接的回调函数，需要由上层用户设置给TcpServer，再由TcpServer设置给新连接*/
    using ConnectedCallback = std::function<void(const ConnPtr&)>;           //连接建立好后应该执行的回调
    using ClosedCallback = std::function<void(const ConnPtr&)>;              //关闭连接的时候需要执行的
    using MessageCallback = std::function<void(const ConnPtr&, Buffer*)>;    //信息处理的回调函数
    using AnyEventCallback = std::function<void(const ConnPtr&)>;            //任意事件触发后执行的回调

    using Functor = std::function<void()>;
private:
    /*对新连接进行一系列的设置*/
    void NewConnection(int fd){
        ++_next_id;
        ConnPtr conn = std::make_shared<Connection>(_pool.NextLoop(), _next_id, fd);
        /*这里直接把成员变量进行赋值设置即可，真正设置的是上层的用户*/
        conn->SetConnectedCallback(_connected);
        conn->SetClosedCallback(_closed);
        conn->SetMessageCallback(_message);
        conn->SetAnyEventCallback(_any);

        conn->SetServerClosedCallback(std::bind(&TcpServer::DelConnection, this, std::placeholders::_1));
        if(_enable_inactive_release) conn->EnableInactiveRelease(_timeout);
        conn->Establish();
        _connections[_next_id] = conn;
    }


    void DelConnectionInLoop(const ConnPtr& conn){_connections.erase(conn->Id());}
    /*针对于Connection会释放连接，也就是内部会调用Remove，那么真正要释放连接的时候，是需要把这里哈希表中保存的ConnPtr给释放*/
    void DelConnection(const ConnPtr& conn){_base_loop.RunInLoop(std::bind(&TcpServer::DelConnectionInLoop, this, conn));}

    void RunAfterInLoop(const Functor& task, int delay){
        ++_next_id;
        _base_loop.TimerAdd(_next_id, delay, task);
    }

public:
    TcpServer(uint32_t port):_port(port), _next_id(0), _enable_inactive_release(false), _timeout(0),_acceptor(&_base_loop, _port),_pool(&_base_loop)
    {
        _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));
        _acceptor.StartListen();
    }
    ~TcpServer(){}

    void SetLoopThreadNum(int num){_pool.SetThreadNum(num);}    //设置从属线程池的线程个数

    //是否需要设置超时任务 -> 其实就是设置一个状态，便于后序进行操作！
    void EnableInactiveRelease(int delay){
        _enable_inactive_release = true;
        _timeout = delay;
    }

    /*外界给设置的新连接的各类回调*/
    void SetConnectedCallback(const ConnectedCallback& cb){_connected = cb;}
    void SetClosedCallback(const ClosedCallback& cb){_closed = cb;}
    void SetMessageCallback(const MessageCallback& cb){_message = cb;}
    void SetAnyEventCallback(const AnyEventCallback& cb){_any = cb;}
    
    /*这里再提供一个操作给用户：就是给baseloop也可以设置超时任务！具体是否适用取决于用户*/
    void RunAfter(const Functor& task, int delay){
        _base_loop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
    }

    void Start(){
        /*线程池创建必须在这里，因为如果在构造那里创建，那时候的threadnum默认是0，所以需要先设置一下！*/
        _pool.StartAllThread();
        while(1){
            _base_loop.Start();
            std::cout << "当前被管理的连接ID:" << std::endl;
            for(auto& it : _connections){
                std::cout << it.first << " ";
            }
            std::cout << std::endl;
        }
    }


private:
    uint32_t _port;                                 //端口号
    int _next_id;                                   //一个自动增长的id，其实就是用来选取一个EventLoop派发
    bool _enable_inactive_release;                  //是否启动连接的超时释放
    int _timeout;                                   //超时时间

    EventLoop _base_loop;                           //主线程对应的EventLoop
    Acceptor _acceptor;                             //用于获取新连接的模块
    ThreadPool _pool;                               //从属Reactor对应的线程
    std::unordered_map<int, ConnPtr> _connections;  //上层用来管理所有新连接的

    ConnectedCallback _connected;
    ClosedCallback _closed;
    MessageCallback _message;
    AnyEventCallback _any;
};


/************************************TCPSERVER模块**************************************/








/*​​SIGPIPE信号​​：
当程序向一个已关闭的 socket 写入数据时，操作系统会触发 SIGPIPE信号
默认行为是终止进程，但这通常不是网络程序期望的行为*/
class NetWork{
public:
    NetWork(){
        LOG(LogLevel::DEBUG) << "SIGPIPE INIT";
        signal(SIGPIPE, SIG_IGN);
    }
};

static NetWork nw;   //实例化一个对象出来，让sigpipe的忽略生效